/*
 * InvulgoTracker
 * Copyright (C) Thomas Andersen 2011 <thomas.1.andersen@gmail.com>
 *
 * InvulgoTracker is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * InvulgoTracker is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>

#include <config.h>

#include "gettextmacro.h"
#include "task-view.h"
#include "task-progress-view.h"
#include "day.h"
#include "invulgotrackerapp.h"


TaskProgressView::TaskProgressView()
{
}


TaskProgressView::~TaskProgressView()
{
    Clean();
}

void TaskProgressView::Clean()
{
    g_object_unref (model);
    gtk_tree_view_set_model (view, NULL);
    while (gtk_tree_view_remove_column(view, gtk_tree_view_get_column(view, 0)) > 0);
}


GtkTreeModel *TaskProgressView::CreateModel()
{
    GtkListStore  *store;

    store = gtk_list_store_new (NUM_COLS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_LONG, G_TYPE_STRING, G_TYPE_STRING);

    return GTK_TREE_MODEL (store);
}



extern "C" gint TaskProgressView::sort_iter_compare_func (GtkTreeModel *model, GtkTreeIter  *a, GtkTreeIter  *b, gpointer userdata)
{
    gint sortcol = GPOINTER_TO_INT(userdata);
    gint ret = 0;

    gchar *name1, *name2;

    gtk_tree_model_get(model, a, sortcol, &name1, -1);
    gtk_tree_model_get(model, b, sortcol, &name2, -1);

    /* Sort by content. */
    switch (sortcol)
    {
    case SORT_TITLE:
        if (name1 == NULL || name2 == NULL)
        {
            if (name1 == NULL && name2 == NULL)
                ;
            else
                ret = (name1 == NULL) ? -1 : 1;
        }
        else
        {
            ret = g_utf8_collate(name1,name2);
        }

        g_free(name1);
        g_free(name2);
        break;
    case SORT_TIME:
        {
            if (name1 == NULL || name2 == NULL)
            {
                if (name1 == NULL && name2 == NULL)
                    break; /* both equal => ret = 0 */

                ret = (name1 == NULL) ? -1 : 1;
            }
            else
            {
                TaskTime t1(name1);
                TaskTime t2(name2);
                if (t1 < t2)
                    ret = -1;
                else if (t1 == t2)
                    ret = 0;
                else
                    ret = 1;
            }

            g_free(name1);
            g_free(name2);
        }
        break;
    case SORT_USED:
        {
            if (name1 == NULL || name2 == NULL)
            {
                if (name1 == NULL && name2 == NULL)
                    break; /* both equal => ret = 0 */

                ret = (name1 == NULL) ? -1 : 1;
            }
            else
            {
                TaskTime t1(name1);
                TaskTime t2(name2);
                if (t1 < t2)
                    ret = -1;
                else if (t1 == t2)
                    ret = 0;
                else
                    ret = 1;
            }

            g_free(name1);
            g_free(name2);
        }
        break;

    default:
        g_return_val_if_reached(0);
    }

    return ret;
}


extern "C" void TaskProgressView::column_time_clicked(GtkTreeViewColumn *treeviewcolumn, gpointer user_data)
{
    TaskProgressView *sv = (TaskProgressView*)user_data;
    sv->ColumnClicked(treeviewcolumn, SORT_TIME);
}

extern "C" void TaskProgressView::column_title_clicked(GtkTreeViewColumn *treeviewcolumn, gpointer user_data)
{
    TaskProgressView *sv = (TaskProgressView*)user_data;
    sv->ColumnClicked(treeviewcolumn, SORT_TITLE);
}

void TaskProgressView::ColumnClicked(GtkTreeViewColumn *treeViewColumn, gint columnSortId)
{
    GtkTreeSortable *sortable;
    GtkSortType      order;
    gint             sortid;

    sortable = GTK_TREE_SORTABLE(model);

    /* If we are already sorting by year, reverse sort order,
     *  otherwise set it to year in ascending order */
    g_object_set(treeViewColumn, "sort-indicator", TRUE ,NULL);
    if (gtk_tree_sortable_get_sort_column_id(sortable, &sortid, &order) == TRUE &&  sortid == columnSortId) {
        GtkSortType neworder;
        neworder = (order == GTK_SORT_ASCENDING) ? GTK_SORT_DESCENDING : GTK_SORT_ASCENDING;
        gtk_tree_sortable_set_sort_column_id(sortable, columnSortId, neworder);
        g_object_set(treeViewColumn, "sort-order", neworder ,NULL);
    } else {
        GList *list = gtk_tree_view_get_columns(view);
        do {
            if (list && list->data != treeViewColumn)
                g_object_set(list->data, "sort-indicator", FALSE ,NULL);
        } while((list = g_list_next(list)));
        g_list_free(list);
        gtk_tree_sortable_set_sort_column_id(sortable, columnSortId, GTK_SORT_ASCENDING);
        g_object_set(treeViewColumn, "sort-order", GTK_SORT_ASCENDING ,NULL);
    }
}


extern "C" void TaskProgressView::column_used_clicked(GtkTreeViewColumn *treeviewcolumn, gpointer user_data)
{
    TaskProgressView *sv = (TaskProgressView*)user_data;
    sv->ColumnClicked(treeviewcolumn, SORT_USED);
}


void TaskProgressView::Restart()
{
    Clean();
    Init(GTK_WIDGET(view));
}

void TaskProgressView::Init(GtkWidget *view)
{
    GtkCellRenderer *renderer;

    this->view = GTK_TREE_VIEW(view);

    model = CreateModel();


    /* Item */
    renderer = gtk_cell_renderer_text_new ();
    GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(_("Item"),  renderer, "text", COL_TITLE, NULL);
    //    gtk_tree_view_column_set_resizable(column, TRUE);
    g_object_set(column, "sizing",GTK_TREE_VIEW_COLUMN_AUTOSIZE,NULL);
    g_object_set(column, "reorderable", TRUE ,NULL);
    g_object_set(column, "clickable", TRUE ,NULL);
    g_object_set(column, "sort-indicator", TRUE ,NULL);
    g_signal_connect(G_OBJECT(column), "clicked", G_CALLBACK(column_title_clicked), this);
    gtk_tree_view_insert_column(GTK_TREE_VIEW (view), column, -1);

    /* Time */
    renderer = gtk_cell_renderer_text_new ();
    g_object_set(renderer, "xalign",1.0,NULL);
    column = gtk_tree_view_column_new_with_attributes(_("Estimate"),  renderer, "text", COL_TIME, NULL);
    g_object_set(column, "reorderable", TRUE ,NULL);
    g_object_set(column, "clickable", TRUE ,NULL);
    g_signal_connect(G_OBJECT(column), "clicked", G_CALLBACK(column_time_clicked), this);
    gtk_tree_view_insert_column(GTK_TREE_VIEW (view), column, -1);

    /* Used */
    renderer = gtk_cell_renderer_text_new ();
    g_object_set(renderer, "xalign",1.0,NULL);
    column = gtk_tree_view_column_new_with_attributes(_("Used"),  renderer, "text", COL_USED, NULL);
    g_object_set(column, "reorderable", TRUE ,NULL);
    g_object_set(column, "clickable", TRUE ,NULL);
    g_signal_connect(G_OBJECT(column), "clicked", G_CALLBACK(column_used_clicked), this);
    gtk_tree_view_insert_column(GTK_TREE_VIEW (view), column, -1);

    /* Progress */
    renderer = gtk_cell_renderer_progress_new();
    column = gtk_tree_view_column_new_with_attributes(_("Used"),  renderer, "value", COL_PCT, "text", COL_PCTTEXT, NULL);
    gtk_tree_view_insert_column(GTK_TREE_VIEW (view), column, -1);


    GtkTreeSortable *sortable = GTK_TREE_SORTABLE(model);
    gtk_tree_sortable_set_sort_func(sortable, SORT_TITLE, sort_iter_compare_func,GINT_TO_POINTER(SORT_TITLE), NULL);
    gtk_tree_sortable_set_sort_func(sortable, SORT_TIME, sort_iter_compare_func,GINT_TO_POINTER(SORT_TIME), NULL);
    gtk_tree_sortable_set_sort_func(sortable, SORT_USED, sort_iter_compare_func,GINT_TO_POINTER(SORT_USED), NULL);
    /* set initial sort order */
    gtk_tree_sortable_set_sort_column_id(sortable, SORT_TITLE, GTK_SORT_ASCENDING);
    gtk_tree_view_set_model (GTK_TREE_VIEW (view), model);

}

void TaskProgressView::Calc()
{
    TimeUsedThread tut;
    GtkTreeIter iter;

    tut.Calc();
    tut.UpdateParents(InvulgoTrackerApp::app->GetTaskView());

    if (tut.Begin()) {
        do {
            TaskId id = tut.GetTaskId();
            TaskTime tt = tut.GetTaskTime();
            glong hours = InvulgoTrackerApp::app->GetTaskView().GetEstimate95(id);
            char hourStr[51];
            sprintf(hourStr,"%ld:00",hours);
            TaskTime estimate = TaskTime(hourStr);
            char *estimateStr = estimate.TimeText();
            char *usedStr = tt.TimeText();
            gchar *title = NULL;
            InvulgoTrackerApp::app->GetTaskView().Get(id, &title);

            hours *= 60;
            glong used = tt.Minutes();
            glong pct;
            if (hours)
                pct = (glong)(((gdouble)used/(gdouble)hours)*100.0);
            else
                pct = 0;
            char pctStr[51];
            sprintf(pctStr,"%ld %%", pct);
            if (pct > 100)
                pct = 100;
            gtk_list_store_append (GTK_LIST_STORE(model), &iter);
            gtk_list_store_set (GTK_LIST_STORE(model), &iter,
                                COL_TITLE, title,
                                COL_USED, usedStr,
                                COL_TIME, estimateStr,
                                COL_PCT, pct,
                                COL_PCTTEXT, pctStr,
                                COL_ID, (const gchar *)id,
                                -1);
            free(usedStr);
            free(estimateStr);
            g_free(title);
        } while(tut.Next());
    }
}


bool TaskProgressView::GetFirst(gchar **name, gchar **timeStr, gchar **usedStr, gchar **pct)
{
    if (gtk_tree_model_get_iter_first(model, &currentIter)) {
        gtk_tree_model_get(model, &currentIter,
                           COL_TITLE, name,
                           COL_TIME, timeStr,
                           COL_USED, usedStr,
                           COL_PCTTEXT, pct,
                           -1);
        return true;
    }
    return false;
}

bool TaskProgressView::GetNext(gchar **name, gchar **timeStr, gchar **usedStr, gchar **pct)
{
    if (gtk_tree_model_iter_next(model, &currentIter)) {
        gtk_tree_model_get(model, &currentIter,
                           COL_TITLE, name,
                           COL_TIME, timeStr,
                           COL_USED, usedStr,
                           COL_PCTTEXT, pct,
                           -1);
        return true;
    }
    return false;
}

